package com.myutils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.w3c.dom.Node;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * @author Lan
 * @date 2012-7-27
 */
public class XmlUtil {
	
	protected static Logger logger = Logger.getLogger(XmlUtil.class);
	
	/**
	 * 将org.w3c.dom类型的xml转换成字符串
	 * @author Lan
	 * @param node
	 * @return
	 */
	public static String xmlToString(Node node) {
		String xmlStr = "";
		try {
			Source source = new DOMSource(node);
			StringWriter stringWriter = new StringWriter();
			Result result = new StreamResult(stringWriter);
			
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();
			transformer.transform(source, result);
			xmlStr = stringWriter.getBuffer().toString();
		} catch (TransformerConfigurationException e) {
			logger.error("TransformerFactory实例化异常", e);
		} catch (TransformerException e) {
			logger.error("Xml对象转化成String字符串时出现异常", e);
		} 
		return xmlStr;
	}

	/**
	 * 保存xml文档(utf-8)到本地
	 * 
	 * @author Lan
	 * @param document
	 * @param savePath
	 *            保存的全路径（路径+文件名）
	 */
	public static boolean outXmlLocal(Document document, String savePath) {
		boolean isSucc = false;
		try {
			FileUtil.createDir(savePath);
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8");

			XMLWriter writer = new XMLWriter(new FileOutputStream(new File(
					savePath)), format);
			writer.write(document);
			writer.close();
			isSucc = true;
			logger.debug("xml的保存路径：" + savePath);
		} catch (Exception e) {
			logger.error("保存xml文件失败", e);
		}
		return isSucc;
	}

	/**
	 * 读取本地xml文件
	 * @author Lan
	 * @param file
	 * @return
	 */
	public static Document getXmlDocument(File file){
		Document document = null;
		SAXReader reader = new SAXReader();
		try {
			document = reader.read(file);
		} catch (DocumentException e) {
			logger.error("读取XML文件错误", e);
		}
		return document;
	}
	
	/**
	 * DTD方式验证xml的规范性
	 * @author Lan
	 * @param doc
	 * @throws UtilityException 
	 */
	public static void validateXmlByDTD(Document doc) {
		try {
			SAXReader reader = new SAXReader(true);
			reader.setEntityResolver(new EntityResolver() {
				public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
					InputSource is = new InputSource(systemId);
					is.setPublicId(publicId);
					return is;
				}
			});
			InputStream in = new ByteArrayInputStream(doc.asXML().getBytes());
			reader.read(in);
		} catch (DocumentException e) {
			logger.error("[DTD方式验证]xml不合法", e);
		}  
	}
	
	/**
	 * Schema方式验证xml的规范性
	 * @author Lan
	 * @param doc
	 * @throws UtilityException 
	 */
	public static void validateXmlByXSD(Document doc) {
        try {
        	SAXReader reader = new SAXReader(true);  
			reader.setFeature("http://xml.org/sax/features/validation", true);
			reader.setFeature("http://apache.org/xml/features/validation/schema", true);  
			reader.setFeature("http://apache.org/xml/features/validation/schema-full-checking",true);  
			//reader.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", PropUtil.getStrValue("xsdFile"));
			InputStream in = new ByteArrayInputStream(doc.asXML().getBytes("UTF-8"));
			reader.read(in);  
		} catch (Exception e) {
			logger.error("[Schema方式验证]xml不合法", e);
		}  
  
	}
}
